import type { LocalProjectItem } from "@common/local-project.types.ts";
import type { ItemType } from "ant-design-vue";
import path from "@/framework/util/path.ts";
import { hci } from "@/components/framework/icon";
import { execInTerminal } from "@/util/system-utils2.ts";
import { hc } from "@/framework/vue/util/render.ts";
import { ClearOutlined, CodeFilled } from "@ant-design/icons-vue";

/**
 * TODO: 根据不同项目类型，获取项目中的启动脚本配置，添加到菜单中快捷调用
 * @param project
 */
export async function getContextMenu(project: LocalProjectItem): Promise<ItemType[]> {
  let items: ItemType[];
  switch (project.type) {
    case "nodejs":
      items = await fromNodejs(project);
      break;
    case "python":
      items = await fromPython(project);
      break;

    case "dotnet":
      items = await fromDotnet(project);
      break;

    default:
      items = [];
  }

  const scripts = await getScriptsMenus(project);
  items.push(...scripts);
  return items;
}

const getProjectPath = (project: LocalProjectItem) => {
  return project.type === "dotnet" ? path.dirname(project.path) : project.path;
};

async function getScriptsMenus(project: LocalProjectItem): Promise<ItemType[]> {
  const projectPath = getProjectPath(project);
  const scripts = await native.fs.readdir(projectPath, {
    depth: 2,
    filter: "**/*.{cmd,bat}",
    ignore: ["node_modules", "obj", "dist", "release"],
  });
  if (scripts.length > 0) {
    return [
      {
        key: "project-scripts",
        label: "运行项目脚本",
        icon: hc(CodeFilled, { style: "font-size:13px;color:green" }),
        children: scripts.map(it => {
          const scriptPath = path.normalize(it);
          const displayName = scriptPath.replace(projectPath, "").replace(/^[\/\\]/, "");
          const cmd = path.basename(scriptPath);
          return {
            key: `script-${displayName}`,
            label: `> ${displayName}`,
            onClick: () => {
              execInTerminal(cmd, { cwd: path.dirname(scriptPath) });
            },
          };
        }),
      },
    ];
  }
  return [];
}

async function fromNodejs(project: LocalProjectItem): Promise<ItemType[]> {
  const items: ItemType[] = [];
  try {
    const packageJsonFile = path.join(project.path, "package.json");
    const packageJson = await native.fs.readFileJson(packageJsonFile);
    const { scripts = {} } = packageJson;
    const commands = Object.keys(scripts);
    if (commands.length > 0) {
      items.push({
        key: "npm-run-scripts",
        label: "运行npm脚本",
        icon: hci("icon-npm", { style: "color:#D14748" }),
        children: commands.map(it => ({
          key: `npm-run-${it}`,
          label: `$ ${it}`,
          onClick: async () => {
            const packageManager = await detectNodejsPackageManager(project, packageJson);
            execInTerminal(`${packageManager} run ${it}`, { cwd: project.path, subPath: ["node_modules/.bin"] });
          },
        })),
      });
    }
  } catch (e) {
    console.error("fromNodejs", e);
  }

  return items;
}

async function detectNodejsPackageManager(project: LocalProjectItem, packageJson: any): Promise<string> {
  if (packageJson.packageManager) {
    const [packageManagerName] = packageJson.packageManager.split("@");
    return packageManagerName;
  }

  // 根据lock文件判断项目使用的包管理器
  if (await native.fs.exists(path.join(project.path, "yarn.lock"))) return "yarn";
  if (await native.fs.exists(path.join(project.path, "pnpm-lock.yaml"))) return "pnpm";
  return "npm";
}

const pythonExcludeScripts = ["config.py", "nb_log_config.py"];

async function fromPython(project: LocalProjectItem): Promise<ItemType[]> {
  const files = await native.fs.readdir(project.path);
  const pyScripts = files.filter(it => it.endsWith(".py") && !pythonExcludeScripts.includes(path.basename(it)));
  return [
    {
      key: "python-run",
      label: "运行Python文件",
      icon: hci("icon-python"),
      children: pyScripts.map(it => {
        const scriptName = path.basename(it);
        return {
          key: `python-${it}`,
          label: `$ ${scriptName}`,
          onClick: async () => {
            execInTerminal(`python ${scriptName}`, {
              cwd: project.path,
              subPath: [".venv/Scripts", "venv/Scripts"],
            });
          },
        };
      }),
    },
  ];
}

async function fromDotnet(project: LocalProjectItem): Promise<ItemType[]> {
  return [
    {
      key: "dotnet-clean",
      label: "清理项目",
      icon: hc(ClearOutlined),
      onClick: () => {
        console.log(project);
        // TODO: 清理dotnet项目中所有的bin,obj目录
      },
    },
  ];
}
